"""
引导加载程序模型，封装OpenBLT库的底层操作
"""
import os
import openblt
from PyQt5.QtCore import QObject, pyqtSignal
import time
import serial.tools.list_ports

class BootloaderModel(QObject):
    # 信号定义（如有需要可保留）
    status_updated = pyqtSignal(str)
    operation_completed = pyqtSignal(bool, str)

    def __init__(self):
        super().__init__()
        self.firmware_file = ""
        self.connected = False
        self.initialized = False
        self.settings = {
            'interface': 'XCP on Modbus RTU',
            'device': 'COM3',
            'baudrate': 115200,
            'parity': 0,
            'stopbits': 1,
            'destination': 2,
            'protocol': 'XCP version 1.0',
            'mode': 0,
            'seed_key_file': '',
            'timeouts': {
                't1': 1000,
                't3': 2000,
                't4': 10000,
                't5': 1000,
                't6': 50,
                't7': 2000
            }
        }

    def set_firmware_file(self, file_path):
        self.firmware_file = file_path

    def update_settings(self, settings):
        self.settings.update(settings)

    def initialize(self):
        if not self.initialized:
            try:
                openblt.firmware_init(openblt.BLT_FIRMWARE_PARSER_SRECORD)
                self.initialized = True
                return True
            except Exception as e:
                self.status_updated.emit(f"OpenBLT库初始化失败: {str(e)}")
                return False
        return True

    def terminate(self):
        if self.initialized:
            try:
                if self.connected:
                    self.disconnect()
                openblt.firmware_terminate()
                self.initialized = False
            except Exception as e:
                self.status_updated.emit(f"终止OpenBLT库失败: {str(e)}")

    def connect(self):
        if not self.initialized:
            if not self.initialize():
                return False
        try:
            interface = self.settings.get('interface', 'XCP on Modbus RTU')
            session_type = openblt.BLT_SESSION_XCP_V10
            session_setting = openblt.BltSessionSettingsXcpV10()
            # 通用session参数
            session_setting.timeoutT1 = self.settings['timeouts']['t1']
            session_setting.timeoutT3 = self.settings['timeouts']['t3']
            session_setting.timeoutT4 = self.settings['timeouts']['t4']
            session_setting.timeoutT5 = self.settings['timeouts']['t5']
            session_setting.timeoutT6 = self.settings['timeouts']['t6']
            session_setting.timeoutT7 = self.settings['timeouts']['t7']
            session_setting.seedKeyFile = self.settings['seed_key_file']
            session_setting.connectMode = self.settings['mode']
            # 动态适配接口
            if interface == 'XCP on RS232':
                transport_type = openblt.BLT_TRANSPORT_XCP_V10_RS232
                transport_setting = openblt.BltTransportSettingsXcpV10Rs232()
                transport_setting.portName = self.settings['device']
                transport_setting.baudrate = self.settings['baudrate']
                transport_setting.csType = self.settings.get('checksum', 0)
            elif interface == 'XCP on CAN':
                transport_type = openblt.BLT_TRANSPORT_XCP_V10_CAN
                transport_setting = openblt.BltTransportSettingsXcpV10Can()
                transport_setting.deviceName = self.settings['device']
                transport_setting.deviceChannel = self.settings['channel']
                transport_setting.baudrate = self.settings['baudrate']
                transport_setting.transmitId = int(self.settings['transmit'], 16)
                transport_setting.receiveId = int(self.settings['receive'], 16)
                transport_setting.useExtended = 1 if self.settings.get('extended', False) else 0
            elif interface == 'XCP on USB':
                transport_type = openblt.BLT_TRANSPORT_XCP_V10_USB
                transport_setting = None  # USB通常不需要额外参数
            elif interface == 'XCP on TCP/IP':
                transport_type = openblt.BLT_TRANSPORT_XCP_V10_NET
                transport_setting = openblt.BltTransportSettingsXcpV10Net()
                transport_setting.address = self.settings['address']
                transport_setting.port = int(self.settings['port'])
            elif interface == 'XCP on Modbus RTU':
                transport_type = openblt.BLT_TRANSPORT_XCP_V10_MBRTU
                transport_setting = openblt.BltTransportSettingsXcpV10MbRtu()
                transport_setting.portName = self.settings['device']
                transport_setting.baudrate = self.settings['baudrate']
                transport_setting.parity = self.settings['parity']
                transport_setting.stopBits = self.settings['stopbits']
                transport_setting.destinationAddr = self.settings['destination']
            else:
                self.status_updated.emit(f"不支持的通讯接口: {interface}")
                return False
            # 初始化session
            openblt.session_init(
                session_type=session_type,
                session_settings=session_setting,
                transport_type=transport_type,
                transport_settings=transport_setting
            )
            # 连接
            start_time = time.time()
            while openblt.session_start() != openblt.BLT_RESULT_OK:
                if time.time() - start_time > 10:
                    self.status_updated.emit("【连接】等待连接超时(10s),连接目标设备失败,请重新开始")
                    return False
                time.sleep(0.01)
            self.status_updated.emit("【连接】连接目标设备成功")
            self.connected = True
            return True
        except Exception as e:
            self.status_updated.emit(f"【连接】连接失败: {str(e)}")
            return False

    def disconnect(self):
        if self.connected:
            try:
                openblt.session_stop()
                openblt.session_terminate()
                self.connected = False
                return True
            except Exception as e:
                self.status_updated.emit(f"断开连接失败: {str(e)}")
                return False
        return True

    def load_firmware(self):
        try:
            openblt.firmware_load_from_file(self.firmware_file)
            return True
        except Exception as e:
            self.status_updated.emit(f"固件加载失败: {str(e)}")
            return False

    def get_segment_count(self):
        return openblt.firmware_get_segment_count()

    def get_segment(self, idx):
        return openblt.firmware_get_segment(idx)

    def erase_chunk(self, addr, length):
        return openblt.session_clear_memory(addr, length)

    def write_chunk(self, addr, data):
        return openblt.session_write_data(addr, len(data), data)

    def get_available_ports(self):
        """获取当前系统可用串口列表"""
        ports = serial.tools.list_ports.comports()
        return [port.device for port in ports] 